package map.adapter;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.ecore.util.EcoreUtil;

import uimigration.Interactions.Behaviour;
import uimigration.Interactions.EditContent;
import uimigration.Interactions.SelectContent;
import uimigration.Interactions.Type;
import uimigration.WidgetsModel.APIModel;
import uimigration.WidgetsModel.Widget;

public class WidgetEquivalence {
	public WidgetEquivalence()
	{
	}
	
	public boolean rootEquivanence(Widget ws, Widget wt)
	{
		if(ws.isIsRoot()&& wt.isIsRoot())
			return true;
		return false;
	}
	private boolean structureEquivalence(Widget ws, Widget wt)
	{
		boolean equivalent= false;
		if(!ws.isIsRoot() &&  !wt.isIsRoot())
		{
			if(ws.isIsContainer()==wt.isIsContainer() && cardinalityEquivalence(ws, wt))
				equivalent=true;
			else if(!ws.isIsContainer() && wt.isIsContainer()&& cardinalityEquivalence(ws, wt))
				equivalent=true;
		}
		return equivalent;
	}
	public boolean containsStructureEquivalence(Widget ws, Widget wt)
	{
		boolean equivalent= false;
		if(ws.getContainsWidgetLength()>0 && wt.getContainsWidgetLength()==0)
			equivalent=false;
		else if(ws.getContainsWidgetLength() == wt.getContainsWidgetLength())
		{
			if(ws.getContainsWidgetLength()==0 && structureEquivalence(ws, wt))
				equivalent=true;
			else if(structureEquivalence(ws, wt))
			{
				int n=ws.getContainsWidgetLength();
				for(int i=0;i<ws.getContainsWidgetLength();i++)
					for(int j=0;j<wt.getContainsWidgetLength();j++)
						if(structureEquivalence(ws.getContainsWidget().get(i),wt.getContainsWidget().get(j)))
							n--;
				if(n==0)
					equivalent=true;
			}	
		}
		else if(ws.getContainsWidgetLength() ==0&& wt.getContainsWidgetLength()>0 && structureEquivalence(ws, wt))
		{
			int n=wt.getContainsWidgetLength();
			for(int i=0;i<wt.getContainsWidgetLength();i++)
				if(structureEquivalence(ws ,wt.getContainsWidget().get(i)))
					n--;
			if(n<wt.getContainsWidgetLength())
				equivalent=true;
		}
		return equivalent;
	}
	
	public boolean contentEquivalent(Widget ws , Widget wt)
	{
		uimigration.WidgetsModel.Property ps, pt;
		ps= getContainProperty(ws);
		pt= getContainProperty(wt);

		if(ps!=null  && pt!=null)
			return true;
		if(ps==null && pt==null)
			return true;
		return false;
		
	}
	private uimigration.WidgetsModel.Property getContainProperty(Widget w)
	{
		if(w.getProperties()!=null && w.getProperties().size()>0)
		for(int i=0;i<w.getProperties().size();i++){

			uimigration.WidgetsModel.Property p =w.getProperties().get(i);
			if(w.getName().contains("Button"))
				System.out.println("pi "+p.getName()+ "\n "+w.getName()+"\n "+p.getRenderingProperty());
			if (p.getRenderingProperty()!=null)
				return EcoreUtil.copy( p);
		}
		return null;
			
	}
	private List<Integer> getCardinality(Widget widget)
	{
		List<Integer> card = new ArrayList<Integer>();
		card.add(0, 0);
		card.add(1,1);
		if(widget.getCardinality()!=null )
		{
			if(widget.getCardinality().size()==1)
			{
				card.set(0, widget.getCardinality().get(0));
				card.set(1, widget.getCardinality().get(0));
			}
			else if(widget.getCardinality().size()==2)
			{
				if(widget.getCardinality().get(0)==-1)
				{	
					card.set(1,widget.getCardinality().get(0) );
					card.set(0,widget.getCardinality().get(1) );
				}
				else if(widget.getCardinality().get(1)==-1)
				{
					card.set(1,widget.getCardinality().get(1) );
					card.set(0,widget.getCardinality().get(0) );
				}
				else if(widget.getCardinality().get(0)<widget.getCardinality().get(1)){
					card.set(0,widget.getCardinality().get(0) );
					card.set(1,widget.getCardinality().get(1) );
				}
			}
				
		}
		return card;
		
	}
	private boolean cardinalityEquivalence(Widget ws, Widget wt)
	{
		List<Integer> cards= getCardinality(ws);
		List<Integer> cardt= getCardinality(wt);
		if(cards.get(0)==cardt.get(0) && cardt.get(1)==cards.get(1))
			return true;
		else if(cards.get(0)==cardt.get(0) && cardt.get(1)==-1)
			return true;
		return false;
	}

	public boolean isContainsWidget(Widget widget, APIModel model)
	{
		for(Widget w  :model.getContains())
		{
			if(w.getContainsWidgetLength()>0)
				if(w.getContainsWidget().get(0).getName().compareTo(widget.getName())==0)
					return true;
		}
		return false;
	}
	public boolean behaviorsEquivalence(Widget ws, Widget wt)
	{
		boolean equivalent= false;
		if(ws.getBehavior().size()<= wt.getBehavior().size())
			if(equivalentWidget(ws, wt))
				equivalent=true;
		return equivalent;
	}
	public boolean equivalentWidget(Widget w1, Widget w2){
		boolean equal=false;
		int found=w1.getBehavior().size();
		for(Behaviour b1: w1.getBehavior()){
			for(Behaviour b2:w2.getBehavior())
				if(equalBehaviour(b1,b2) )
				{
					found--;
					break;
				}
		}
		if(found<=0 && equivalentProperties(w1, w2))
			equal=true;
		return equal;
	}	
	
	private boolean equalBehaviour(Behaviour b1, Behaviour b2)
	{
		if(b1.eClass().getName().compareTo(b2.eClass().getName())==0)
		{
			try {
				if(((EditContent)b1).getEditatbleContent()!=null && ((EditContent)b2).getEditatbleContent()!=null)
				{
					int n =((EditContent)b1).getEditatbleContent().size();
					if(n==0)
						return false;
					if(((EditContent)b1).getEditatbleContent().size()== ((EditContent)b2).getEditatbleContent().size()){
						for(int i=0;i<((EditContent)b1).getEditatbleContent().size();i++)
						{
							if(((EditContent)b1).getEditatbleContent().get(i)==(((EditContent)b1).getEditatbleContent().get(i)))
								if(((EditContent)b1).getEditatbleContent().get(i).getHasType() != null && ((EditContent)b2).getEditatbleContent().get(i).getHasType() != null)
								{
									Type t1 =((EditContent)b1).getEditatbleContent().get(i).getHasType().getType();
									Type t2 =((EditContent)b2).getEditatbleContent().get(i).getHasType().getType();
									if(equivalentType(t1, t2))
										n--;
								}
								
						}
					}
					if( n==0)
						return true;
					else 
						return false;
				}
				else
					return false;
			} catch (ClassCastException e) {
				try {
					if(((SelectContent)b1).getSelectableContentList()!=null && ((SelectContent)b2).getSelectableContentList()!=null)
					{
						int n =((SelectContent)b1).getSelectableContentList().size();
						if(n==0)
							return false;
						if(((SelectContent)b1).getSelectableContentList().size()== ((SelectContent)b2).getSelectableContentList().size()){
							for(int i=0;i<((SelectContent)b1).getSelectableContentList().size();i++)
							{
								if(((SelectContent)b1).getSelectableContentList().get(i)==(((SelectContent)b1).getSelectableContentList().get(i)))
								{
									Type t1 =((SelectContent)b1).getSelectableContentList().get(i).getHasType().getType();
									Type t2 =((SelectContent)b2).getSelectableContentList().get(i).getHasType().getType();
									if(equivalentType(t1, t2))
										n--;
								}
							}
						}
						if( n==0)
							return true;
						else 
							return false;
					}
					else
						return false;
				} catch (ClassCastException e2) {
					return true;
				}
			}
			
		}
		return false;
	}

	private boolean equivalentType(Type t1, Type t2)
	{
		
		if (t1.compareTo(t2)==0)
			return true;
		else
		{
			if (t1.equals(Type.INTEGER) && t2.equals(Type.STRING))
				return true;
			if(t1.equals(Type.IMAGE) && t2.equals(Type.OBJECT))
				return true;
			if(t1.equals(Type.SOUND) && t2.equals(Type.OBJECT))
				return true;
			return false;
		}
	}
	private boolean equivalentProperties(Widget ws, Widget wt)
	{
		int equi=ws.getProperties().size();
		for(uimigration.WidgetsModel.Property ps: ws.getProperties())
		{
			for(uimigration.WidgetsModel.Property pt: wt.getProperties())
			{
				if(ps.getRenderingProperty()==pt.getRenderingProperty() )
					equi--;
				else if(ps.getRenderingProperty() !=null && pt.getRenderingProperty() !=null)
					if(ps.getDataType()!=null&&( ps.getDataType().compareTo(pt.getDataType())==0 || ps.getDataType().contains("Int") && pt.getDataType().contains("String")))
						equi--;
					else if(ps.getDataType()==pt.getDataType())
						equi--;

			}
		}
		if(equi<=0)
			return true;
		else return false;
	}

	public  boolean equivalentBehavior (List<Behaviour> eList, List<Behaviour> eList1)
	{
		boolean equal=false;
		int found=eList.size();
		for(Behaviour b1: eList){
			for(Behaviour b2:eList1)
				if(equalBehaviour(b1,b2) )
				{
					found--;
					break;
				}
		}
		if(found<=0 )
			equal=true;
		return equal;

	}
}
